unit uRace.local;

interface

uses  SysUtils,

      uDefs.local, uDriver.local;

type
  //================================ RACE CONTROL
  TRace = class( TObject )
  public
    Session   : string;
    Lap       : integer;
    TotalLaps : integer;

    Grid      : array of integer; //Grid, who is where

    Weather   : integer; // degrees of rain. 0 = Sunny, 5 = no rain,  10 = downpour
    Predicted : integer; // End point of weather Cycle.
    Temp      : integer; // Effects: Tyre Wear, Tyre Grip, Engine Performance.

    FastestDriver : TFastestLap;

    TrackID : integer;

    constructor Create(DriverCount:integer);
    destructor Destroy; override;

    procedure New();

    function RacingEvents(var nDriver:TDriverItem):string;
    function Time_RandomEvent(var nDriver:TDriverItem):real;
    function Time_TravelPitlane():real; //Returns the time taken to drive the pit lane, for either pit stops or penalties (Pitlane length depends on track)
    function Time_FuelPerLap(Fuel:real):real;
  end;

implementation

uses Math,

     uDebug.common, uSecondsToTime.common,

     uFuncs.local;

  //================================ RACE
constructor TRace.Create(DriverCount:integer);
begin
  inherited Create;

  DevConsole.Msg(ES_DEBUG, '[TRace.Create]');

  SetLength( Grid, DriverCount );

  FastestDriver := TFastestLap.Create();
end;
destructor TRace.Destroy;
begin
  SetLength( Grid, 0 );

  inherited Destroy;
end;

procedure TRace.New();
var G : integer;
begin
  DevConsole.Msg(ES_DEBUG, '[TRace.New]');

  for G := 0 to High( Grid ) do
    Grid[G] := G; //Set the grid linked to driver list.

  Lap       := 0;
  TotalLaps := 0;
  Weather   := 0;
  Predicted := 0;
  Temp      := 0;
end;
function TRace.RacingEvents(var nDriver:TDriverItem):string; // All things like crashes and slipstreams happens here, all things out of a drivers control.
begin
  result := '';

  with nDriver do
  begin
    Status := [STATUS_RACING];

    //====== Random Event
    case (Random(5000)) of   //Leave at 1000
      0..2    : Status := Status + [STATUS_PUNCTURE];  // 3 in 5000 chance
      3..5    : Status := Status + [STATUS_SPIN];      // 3 in 5000 chance
      6..55   : Status := Status + [STATUS_BOOST];     // 45 in 5000 chance
      56..70  : Status := Status + [STATUS_OFFROAD];   // 15 in 5000 chance
      71      : Status := Status + [STATUS_PENALTY];   // 1 in 5000 chance
      72..100  : Status := Status + [STATUS_LOCKUP];   // 28 in 5000 chance
      101..4000  : begin
        if (STATUS_PITTING in Status) then
          Status := Status + [STATUS_PITERROR]; // 1 in 5000 chance
      end;
    end;

    if (GridSlot > 0)and(Session = SESSION_RACE) then
    begin
      if (TimeToNextDriver <= 0.45) then //Decreased from 0.65
        Status := Status + [STATUS_DIRTYAIR]
      else
      if (TimeToNextDriver <= 3.0) then //Increased from 1.5
        Status := Status + [STATUS_SLIPSTREAM]
      else
        Status := Status + [STATUS_PIGEON]; //Catch the pigeon (aka lead driver)
    end;
  end;
end;
function TRace.Time_RandomEvent(var nDriver:TDriverItem):real;
begin
  result := 0;
  with nDriver do
  begin
    if (STATUS_PUNCTURE in Status) then result := result + (20 + (Random(30000)/1000)){ * (SkillFocus/100)};
    if (STATUS_SPIN     in Status) then result := result + (2 + Random(15)) * (SkillFocus/100);
    if (STATUS_BOOST    in Status) then result := result + -((Random(1000)/1000) * (SkillFocus/100));
    if (STATUS_PENALTY  in Status) then result := result + Time_TravelPitlane();
    if (STATUS_OFFROAD  in Status) then result := result + (Random(6000)/1000) * (SkillFocus/100);
    if (STATUS_CRASH    in Status) then result := result + 30 +(Random(60000)/1000) + Time_TravelPitlane();
    if (STATUS_LOCKUP   in Status) then result := result + (Random(100)/1000);
    if (STATUS_PITERROR in Status) then result := result + 1+(random(8000)/1000); // big delay to do a pit stop, 5 in 100 chance (5%)
 end;
end;
function TRace.Time_TravelPitlane():real; //Calcs the time taken to drive the pit lane, for either pit stops or penalties
begin
  result := 20;
end;
function TRace.Time_FuelPerLap(Fuel:real):real;
var TotalFuelWeight : real;
begin
//  DevConsole.Msg(ES_DEBUG, '[TRace.AddTime_FuelPerLap()]');

  TotalFuelWeight := Fuel * FUEL_LITRE_KG;

  result := TotalFuelWeight * FUEL_TIME_KG;
end;

end.

